home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 7 / PC World Interactive 7.iso / program / ctutor.exe / SOURCE / VC.C < prev    next >
C/C++ Source or Header  |  1994-05-15  |  15KB  |  350 lines

  1. /* VC.C - Main Program - Visual Calculator                         */
  2. /* Copyright (c) 1994 Coronado Enterprises                         */
  3. /*                                                                 */
  4. /* This program will evaluate single value expressions in a manner */
  5. /*  similar to those evaluated by a hand-held calculator, hence    */
  6. /*  its name, the Visual Calculator.                               */
  7. /*                                                                 */
  8. /* Although this is a potentially useful program in its own right, */
  9. /*  it was originally written as an illustration of a rather large */
  10. /*  C program. It is especially useful because the student of C    */
  11. /*  can run the program to determine its operating characteristics,*/
  12. /*  then study the code needed to perform the various operations.  */
  13.  
  14. #include <ctype.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <conio.h>
  18. #include <process.h>
  19. #include "vc.h"
  20. #include "video.h"
  21.  
  22. struct vars allvars[12];  /* this is the main variable storage     */
  23. int varinuse = 0;         /* which variable is being used now      */
  24. char inline[200];         /* input line area                       */
  25. int col;                  /* used for searching across the input   */
  26. int errcode;              /* error code number                     */
  27. int colerr;               /* column where error occurred           */
  28. int printit = 0;          /* 1 = print a transcript                */
  29. int ignore;               /* 1 = ignore calculations for line      */
  30. extern char strngout[];   /* output message area                   */
  31. FILE *prtfile;            /* file pointers                         */
  32.  
  33. struct lines *top, *bot, *q, *p, *arrow, *trnsend;
  34.  
  35.  
  36.  
  37. /************************************************************ main */
  38. /* This is the main control loop for the program. It initializes   */
  39. /* everything and reads statements until no errors are found. It   */
  40. /* continues reading until an F10 is detected in a subordinate     */
  41. /* function where control is returned to DOS                       */
  42. void main(void)
  43. {
  44.    top = bot = q = p = arrow = trnsend = NULL;
  45.    
  46.    monitor();          /* initialize video attributes              */
  47.    initdata(allvars);  /* initialize all data                      */
  48.    bkgndvid();         /* display video background - double lines  */
  49.    valusvid(allvars);  /* display starting values of all variables */
  50.    strtrans("Welcome to the Visual Calculator - Version 2.00", 0);
  51.    transout();
  52.    do{
  53.       poscurs(23, 7);
  54.       printf("  input >                                 ");
  55.       printf("                              ");
  56.       do {                     /* repeat input until no errors      */
  57.          readline();           /* get an input line                 */
  58.          errdis("                         ");  /* clear error msg   */
  59.          parse();              /* parse the line                    */
  60.          if (errcode) 
  61.             errout();          /* output error message              */
  62.       } while (errcode);
  63.       if (ignore == 1)
  64.          strtrans(inline, 0);  /* store comment in transcript       */
  65.       else
  66.          strtrans(inline, 1);  /* store "inline" in transcript      */
  67.       transout();
  68.    } while (1);                /* continuous loop                   */
  69. }
  70.  
  71.  
  72.  
  73. /******************************************************** readline */
  74. /* This function reads a line by inputting one character at a time */
  75. /* and deciding what to do with it if it is a special character,   */
  76. /* or adding it to the input line if it is a special character.    */
  77. /* The routine takes care of such things as backspace, cursor      */
  78. /* movement and delete keys. The final result is a single line of  */
  79. /* text stored in the buffer "inline" and the line displayed on    */
  80. /* the monitor.                                                    */
  81. void readline(void)
  82. {
  83. int index;
  84. int c, temp;
  85. int row = 23, col = 17;
  86.  
  87.    if (errcode) {           /* error recovery allow reenter        */
  88.       index = colerr;
  89.       errcode = 0;
  90.    } else {                 /* normal input routine                */
  91.       index = 0;
  92.       for (temp = 0 ; temp < 80 ; temp++)
  93.          inline[temp] = 0;  /* clear input buffer                  */
  94.    }
  95.  
  96.    poscurs(row, col + index); /* starting location of cursor       */
  97.  
  98.    do {                     /* repeat this loop until return hit   */
  99.       while ((c = getch()) == EOF);   /* get a keystroke           */
  100.  
  101.       if (c == 0) {         /* a zero says a special key was hit   */
  102.                             /* get the key and act on it as needed */
  103.          int spec;
  104.          spec = getch();    /* this is the special code found      */
  105.          switch (spec) {
  106.             case 59 : helpm();               /* F1 - Help math     */
  107.                       transout();
  108.                       break;
  109.             case 60 : helps();               /* F2 - Help system   */
  110.                       transout();
  111.                       break;
  112.             case 61 : if (printit) {         /* F3 - Print on/off  */
  113.                          printit = 0;        /* print off          */
  114.                          fprintf(prtfile, "%s\n\n", "Print off");
  115.                          fclose(prtfile);
  116.                          strcpy(strngout, "-----");
  117.                          strngdis_help(1, 73);
  118.                       } else {
  119.                          prtfile = fopen("PRN", "w"); /* print on  */
  120.                          if (prtprblm()) {
  121.                             errcode = 12;  /* printer is not ready */
  122.                             errout();
  123.                             break;
  124.                          }
  125.                          printit = 1;
  126.                          fprintf(prtfile, "%s\n", "Print On");
  127.                          strcpy(strngout, "Print");
  128.                          strngdis_val(1, 73);
  129.                       }
  130.                       break;
  131.             case 62 :                      /* F4 - Mark transcript */
  132.                       arrow->marked = (arrow->marked ? 0 : 1);
  133.                       transout();
  134.                       break;
  135.             case 63 : fileout();           /* F5 - Store transcript*/
  136.                       break;
  137.             case 64 : filein();            /* F6 - Retrieve trans  */
  138.                       errcode = 0;
  139.                       break;
  140.             case 65 :                      /* F7 -                 */
  141.                       break;
  142.             case 66 :                      /* F8 -                 */
  143.                       break;
  144.             case 67 :                      /* F9 - Edit a line     */
  145.                       strcpy(inline, arrow->lineloc);
  146.                       poscurs(23, 17);
  147.                       printf("%s", inline);
  148.                       break;
  149.             case 68 : poscurs(23, 17);     /* F10 - Quit to DOS    */
  150.                       printf("Quit? (Y/N) ");
  151.                       c = getch();
  152.                       if ((c == 'Y') || (c == 'y')){
  153.                          clrscrn();
  154.                          exit(0);
  155.                       }
  156.                       poscurs(23, 17);
  157.                       printf("              ");
  158.                       break;
  159.             case 75 : if (index) {         /* left arrow           */
  160.                          index = index -1; /* back up cursor       */
  161.                       }
  162.                       break;
  163.             case 77 : if (index < 65) {    /* right arrow          */
  164.                          if (inline[index] == 0) /* zero found     */
  165.                             inline[index] = ' '; /* blank over 0   */
  166.                          index = index + 1;  /* cursor forward     */
  167.                       }
  168.                       break;
  169.             case 72 : movarrow(-1);        /* up arrow             */
  170.                       break;
  171.             case 80 : movarrow(1);         /* down arrow           */
  172.                       break;
  173.             case 73 : movarrow(-8);        /* page up              */
  174.                       break;
  175.             case 81 : movarrow(8);         /* page down            */
  176.                       break;
  177.             case 71 : movarrow(-1000);     /* home                 */
  178.                       break;
  179.             case 79 : movarrow(1000);      /* end                  */
  180.                       break;
  181.             case 83 : temp = index;        /* delete key           */
  182.                              /* move all characters left one space */
  183.                       while (inline[temp]) {
  184.                          inline[temp] = inline[temp + 1];
  185.                          putchar(inline[temp++]);
  186.                       }
  187.                       putchar(0);          /* zero in last place   */
  188.                       break;
  189.             default : poscurs(15, 5);
  190.                       printf(" S%3d", spec);
  191.          }
  192.          poscurs(row, col + index);      /* put cursor in position */
  193.       }
  194.  
  195.       else {                          /* normal letter or char hit */
  196.          int curr, next;
  197.          if (islower(c))
  198.             c = toupper(c);  /* convert to upper case */
  199.          if ((c >= '\40') && (c <= '\176')) { /* printable char    */
  200.             poscurs(row, col + index);
  201.             putchar(c);
  202.             next = inline[index];
  203.             inline[index++] = c;
  204.             curr = index;
  205.             while((next != 0) && (curr <= 65)) { /* move remainder */
  206.                temp = next;                   /* line right        */
  207.                next = inline[curr];
  208.                inline[curr++] = temp;
  209.                putchar(temp);
  210.             }
  211.          } else {
  212.             if ((c == 8) && index) {          /* backspace         */
  213.                index--;
  214.                poscurs(row, col + index);     /* back up cursor    */
  215.                temp = index;
  216.                while (inline[temp]) {
  217.                   inline[temp] = inline[temp + 1];
  218.                   putchar(inline[temp++]);
  219.                }
  220.                putchar(0);
  221.             }
  222.          }
  223.          poscurs(row, col + index);
  224.       }
  225.       if (c == 3) exit(0);               /* ctrl-break, out to DOS */
  226.    } while (c != 13);     /* newline found, line input is complete */
  227. }
  228.  
  229.  
  230.  
  231. /*********************************************************** parse */
  232. /* This function does a lot of checking of the input line for      */
  233. /* logical errors in construction, then turns control over to the  */
  234. /* function "calcdata" for the actual calculations.                */
  235. void parse(void)
  236. {
  237. int index, parcol;
  238. double newval;
  239. char name[7];
  240.  
  241.    varinuse = -1;
  242.    errcode = 0;
  243.    col = 0;
  244.    ignore = 1;                        /* ignore this line          */
  245.  
  246.    if (inline[0] == '#') {           /* get list of variable names */
  247.       getnames();
  248.       return;
  249.    }
  250.  
  251.    while (inline[col] == ' ') col++;  /* ignore leading blanks     */
  252.    if (inline[col] == '$') return;    /* ignore a comment line     */
  253.    if (inline[col] == 0) return;      /* ignore a blank line       */
  254.    ignore = 0;                        /* don't ignore this line    */
  255.  
  256.    name[0] = inline[col++];           /* find variable name        */
  257.    index = 1;
  258.    while ((((inline[col] >= 'A') && (inline[col] <= 'Z')) ||
  259.           ((inline[col] >= '0') && (inline[col] <= '9'))) &&
  260.           (index <= 5)) {         /* continue var or function name */
  261.       name[index++] = inline[col++];
  262.    }
  263.    name[index] = 0;                   /* name found                */
  264.  
  265.    for (index = 0 ; index < 12 ; index++) {
  266.       if ((strcmp(name, allvars[index].varname)) == 0)
  267.          varinuse = index;            /* variable name found       */
  268.    }
  269.    if (varinuse < 0) 
  270.       errchk(3);                      /* unknown variable name     */
  271.  
  272.    while (inline[col] == ' ') 
  273.       col++;                          /* ignore leading blanks     */
  274.    if (inline[col] == '=') 
  275.       col++;
  276.    else 
  277.       errchk(8);                      /* missing equal sign        */
  278.  
  279.    parcol = 0;        /* now check for correct parenthesis matchup */
  280.    index = col;
  281.    do {
  282.       if (inline[col] == '(') 
  283.          parcol++;
  284.       if (inline[col++] == ')') 
  285.          parcol--;
  286.       if (parcol < 0) 
  287.          errchk(1);                   /* paren count went negative */
  288.    } while (inline[col]);
  289.    if (parcol)
  290.       errchk(2);                      /* left over parentheses     */
  291.    col = index;
  292.  
  293.    calcdata(&newval);       /* now go evaluate the full expression */
  294.    if (errcode == 0) {        /* don't update value if error found */
  295.       allvars[varinuse].value = newval;
  296.       disnew(varinuse, allvars);      /* display the changed value */
  297.    }
  298. }
  299.  
  300.  
  301.  
  302. /********************************************************** errout */
  303. /* This is the function that displays the blinking error message   */
  304. /*  on the monitor. Note the extra errors for expansion of the     */
  305. /*  table.                                                         */
  306. void errout(void)
  307. {
  308.    switch (errcode) {
  309.       case  1 : errdis("extra right parentheses  ");
  310.                 break;
  311.       case  2 : errdis("missing right parentheses");
  312.                 break;
  313.       case  3 : errdis("unknown variable name    ");
  314.                 break;
  315.       case  4 : errdis("invalid math operator    ");
  316.                 break;
  317.       case  5 : errdis("negative value for SQRT  ");
  318.                 break;
  319.       case  6 : errdis("function not found      ");
  320.                 break;
  321.       case  7 : errdis("negative value for LOG   ");
  322.                 break;
  323.       case  8 : errdis("equal sign missing       ");
  324.                 break;
  325.       case  9 : errdis("invalid data field       ");
  326.                 break;
  327.       case 10 : errdis("division by zero         ");
  328.                 break;
  329.       case 11 : errdis("File doesn't exist       ");
  330.                 break;
  331.       case 12 : errdis("Printer not ready        ");
  332.                 break;
  333.       case 13 : errdis("Out of memory            ");
  334.                 break;
  335.       case 14 : errdis("Dash expected            ");
  336.                 break;
  337.       case 15 : errdis("Invalid format code      ");
  338.                 break;
  339.       case 16 : errdis("Neg value for FACTORIAL  ");
  340.                 break;
  341.       case 17 : errdis("Err 17                   ");
  342.                 break;
  343.  
  344.       default : errdis("unknown error            ");
  345.                 poscurs(21, 70);
  346.                 printf("%d", errcode);
  347.    }
  348.    poscurs(23, 12 + colerr);
  349. }
  350.